<!DOCTYPE html>
<html lang="zh-CN">
  <head>
  <meta charset="UTF-8">
  <meta 
    name="viewport"
    content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  <meta 
    http-equiv="X-UA-Compatible" 
    content="ie=edge">
  <meta 
    name="theme-color" 
    content="#fff" 
    id="theme-color">
  <meta 
    name="description" 
    content="霜序廿的个人网站">
  <link 
    rel="icon" 
    href="https://api2.mubu.com/v3/photo/654b368e-b847-4122-982c-86d90b3f5275.jpg">
  <title>http/https详细解读</title>
  
    
      <meta 
        property="og:title" 
        content="http/https详细解读">
    
    
      <meta 
        property="og:url" 
        content="https://shuangxunian.github.io/2021/06/13/https/index.html">
    
    
      <meta 
        property="og:img" 
        content="https://api2.mubu.com/v3/photo/654b368e-b847-4122-982c-86d90b3f5275.jpg">
    
    
      <meta 
        property="og:img" 
        content="一篇关于http/https的文章">
    
    
      <meta 
        property="og:type" 
        content="article">
      <meta 
        property="og:article:published_time" 
        content="2021-06-13">
      <meta 
        property="og:article:modified_time" 
        content="2020-09-24">
      <meta 
        property="og:article:author" 
        content="霜序廿">
      
        
          <meta 
            property="og:article:tag" 
            content="面试">
        
          <meta 
            property="og:article:tag" 
            content="网络">
        
      
    
  
  <script>
    function loadScript(url, cb) {
      var script = document.createElement('script');
      script.src = url;
      if (cb) script.onload = cb;
      script.async = true;
      document.body.appendChild(script);
    }
    function loadCSS(href, data, attr) {
      var sheet = document.createElement('link');
      sheet.ref = 'stylesheet';
      sheet.href = href;
      sheet.dataset[data] = attr;
      document.head.appendChild(sheet);
    }
    function changeCSS(cssFile, data, attr) {
      var oldlink = document.querySelector(data);
      var newlink = document.createElement("link");
      newlink.setAttribute("rel", "stylesheet");
      newlink.setAttribute("href", cssFile);
      newlink.dataset.prism = attr;
      document.head.replaceChild(newlink, oldlink);
    }
  </script>
  
    
      
      
      
      
        
        
        
        <script>
          function prismThemeChange() {
            if(document.getElementById('theme-color').dataset.mode === 'dark') {
              if(document.querySelector('[data-prism]')) {
                changeCSS('/js/lib/prism/prism-tomorrow.min.css', '[data-prism]', 'prism-tomorrow');
              } else {
                loadCSS('/js/lib/prism/prism-tomorrow.min.css', 'prism', 'prism-tomorrow');
              }
            } else {
              if(document.querySelector('[data-prism]')) {
                changeCSS('/js/lib/prism/prism.min.css', '[data-prism]', 'prism');
              } else {
                loadCSS('/js/lib/prism/prism.min.css', 'prism', 'prism');
              }
            }
          }
          prismThemeChange()
        </script>
      
      
        
        <link rel="stylesheet" href="/js/lib/prism/prism-line-numbers.min.css">
      
    
  
  <script>
    // control reverse button
    var reverseDarkList = {
      dark: 'light',
      light: 'dark'
    };
    var themeColor = {
      dark: '#1c1c1e',
      light: '#fff'
    }
    // get the data of css prefers-color-scheme
    var getCssMediaQuery = function() {
      return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
    };
    // reverse current darkmode setting function
    var reverseDarkModeSetting = function() {
      var setting = localStorage.getItem('user-color-scheme');
      if(reverseDarkList[setting]) {
        setting = reverseDarkList[setting];
      } else if(setting === null) {
        setting = reverseDarkList[getCssMediaQuery()];
      } else {
        return;
      }
      localStorage.setItem('user-color-scheme', setting);
      return setting;
    };
    // apply current darkmode setting
  </script>
  
    <script>
      var setDarkmode = function(mode) {
      var setting = mode || localStorage.getItem('user-color-scheme');
      if(setting === getCssMediaQuery()) {
        document.documentElement.removeAttribute('data-user-color-scheme');
        localStorage.removeItem('user-color-scheme');
        document.getElementById('theme-color').content = themeColor[setting];
        document.getElementById('theme-color').dataset.mode = setting;
        prismThemeChange();
      } else if(reverseDarkList[setting]) {
        document.documentElement.setAttribute('data-user-color-scheme', setting);
        document.getElementById('theme-color').content = themeColor[setting];
        document.getElementById('theme-color').dataset.mode = setting;
        prismThemeChange();
      } else {
        document.documentElement.removeAttribute('data-user-color-scheme');
        localStorage.removeItem('user-color-scheme');
        document.getElementById('theme-color').content = themeColor[getCssMediaQuery()];
        document.getElementById('theme-color').dataset.mode = getCssMediaQuery();
        prismThemeChange();
      }
    };
    setDarkmode();
    </script>
  
  
  <link rel="preload" href="//at.alicdn.com/t/font_1946621_i1kgafibvw.css" as="style" >
  <link rel="preload" href="//at.alicdn.com/t/font_1952792_89b4ac4k4up.css" as="style" >
  
  
    <link rel="preload" href="/js/lib/lightbox/baguetteBox.min.js" as="script">
    <link rel="preload" href="/js/lib/lightbox/baguetteBox.min.css" as="style" >
  
  
    <link rel="preload" href="/js/lib/lozad.min.js" as="script">
  
  
  
  
  
  
  
  <link rel="stylesheet" href="/css/main.css">
  
  <link rel="stylesheet" href="//at.alicdn.com/t/font_1946621_i1kgafibvw.css">
  
  <link rel="stylesheet" href="//at.alicdn.com/t/font_1952792_89b4ac4k4up.css">
  
    <link rel="stylesheet" href="/js/lib/lightbox/baguetteBox.min.css">
  
<meta name="generator" content="Hexo 5.4.0"></head>

  <body>
    <div class="wrapper">
       
      <nav class="navbar">
  <div class="navbar-logo">
    <span class="navbar-logo-main">
      
        <img 
          class="navbar-logo-img" 
          src="https://api2.mubu.com/v3/photo/654b368e-b847-4122-982c-86d90b3f5275.jpg" 
          alt="blog logo">
      
      <span class="navbar-logo-dsc">霜序廿的个人网站</span>
    </span>
  </div>
  <div class="navbar-menu">
    
      <a 
        href="/" 
        class="navbar-menu-item">
        
          首页
        
      </a>
    
      <a 
        href="/archives" 
        class="navbar-menu-item">
        
          归档
        
      </a>
    
      <a 
        href="/tags" 
        class="navbar-menu-item">
        
          标签
        
      </a>
    
      <a 
        href="/categories" 
        class="navbar-menu-item">
        
          分类
        
      </a>
    
      <a 
        href="/about" 
        class="navbar-menu-item">
        
          关于
        
      </a>
    
      <a 
        href="/links" 
        class="navbar-menu-item">
        
          友链
        
      </a>
    
    <a 
      class="navbar-menu-item darknavbar" 
      id="dark">
      <i class="iconfont icon-weather"></i>
    </a>
    <a 
      class="navbar-menu-item searchnavbar" 
      id="search">
      <i 
        class="iconfont icon-search" 
        style="font-size: 1.2rem; font-weight: 400;">
      </i>
    </a>
  </div>
</nav> 
      
      <div 
        id="local-search" 
        style="display: none">
        <input
          class="navbar-menu-item"
          id="search-input"
          placeholder="请输入搜索内容..." />
        <div id="search-content"></div>
      </div>
      
      <div class="section-wrap">
        <div class="container">
          <div class="columns">
            <main class="main-column">
<article class="card card-content">
  <header>
    <h1 class="post-title">
      http/https详细解读
    </h1>
  </header>
  <div class="post-meta post-show-meta">
    <time datetime="2021-06-13T13:48:56.143Z">
      <i 
        class="iconfont icon-calendar" 
        style="margin-right: 2px;">
      </i>
      <span>2021-06-13</span>
    </time>
    
      <span class="dot"></span>
      
        <a 
          href="/categories/%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0/" 
          class="post-meta-link">
          技术文章
        </a>
      
    
    
      <span class="dot"></span>
      <span>8k 字</span>
    
  </div>
  
    <div 
      class="post-meta post-show-meta" 
      style="margin-top: -10px;">
      <div style="display: flex; align-items: center;">
        <i 
          class="iconfont icon-biaoqian" 
          style="margin-right: 2px; font-size: 1.15rem;">
        </i>
        
          
          <a 
            href="/tags/%E9%9D%A2%E8%AF%95/" 
            class="post-meta-link">
            面试
          </a>
        
          
            <span class="dot"></span>
          
          <a 
            href="/tags/%E7%BD%91%E7%BB%9C/" 
            class="post-meta-link">
            网络
          </a>
        
      </div>
    </div>
  
  </header>
  <div 
    id="section" 
    class="post-content">
    <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p><strong>URI</strong>：统一资源标识符。互联网的唯一ID<br><strong>HTML</strong>：超文本文档<br><strong>HTTP</strong>:传输超文本的文本传输协议</p>
<h2 id="HTTP是什么"><a href="#HTTP是什么" class="headerlink" title="HTTP是什么"></a>HTTP是什么</h2><p>HTTP(hypertext transport protocol)翻译过来为”超文本传输协议”，文本可以理解为简单的字符文字组合，也可以理解为更为复杂的音频或者图像等。那么将这个词语拆分为三个部分。</p>
<p><strong>超文本</strong>和”文本”相比多了一个字”超”，这样看来比文本丰富，因为它可以将多种文本/图像等进行混合，更重要的是可以从一个文本跳转到另一个文本(文本连接)。</p>
<p><strong>传输</strong>，传输的过程中需要沟通，沟通即可能一对一沟通也可能一对多沟通(进行内容协商)，无论怎么样，参加沟通的人数&gt;1，想尽一切一切办法更快更好的完成相应的任务。</p>
<p><strong>协议</strong>，无规矩不成方圆，做机密项目之前需要签署保密协议，找工作要签”三方协议”，三方协议是学校，公司，和个人组成的协议，都是为了让大家受一定的约束，违反了即有相应的惩罚。</p>
<h2 id="不同版本的HTTP"><a href="#不同版本的HTTP" class="headerlink" title="不同版本的HTTP"></a>不同版本的HTTP</h2><p><strong>HTTP/0.9</strong></p>
<p>当时网络资源匮乏，0.9版本相对简单，采用纯文本格式，且设置为只读，所以当时只能使用”Get”的方式从服务器获得HTML文档，响应以后则关闭。如下所示</p>
<pre class="line-numbers language-html" data-language="html"><code class="language-html">GET /Mysite.html<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>

<p>响应中只包含了文档本身。响应内容无响应头，无错误码，无状态码。</p>
<pre class="line-numbers language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>HTML</span><span class="token punctuation">></span></span>
Hello world
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>HTML</span><span class="token punctuation">></span></span>
HTTP/1.0<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>

<p>此时HTTP/0.9请求过程如下：</p>
<ul>
<li>应用层的HTTP建立在传输层的TCP之上并运用TCP可靠性等特性，先<a target="_blank" rel="noopener" href="https://shuangxunian.gitee.io/2020/09/01/TCP%E9%9D%A2%E8%AF%95%E9%A2%98/">三次握手</a>，建立连接</li>
<li>客户端请求建立连接(此时只有GET)</li>
<li>服务端响应请求，数据以 ASCII 字符流返回给客戶端</li>
<li>传输完成，<a target="_blank" rel="noopener" href="https://shuangxunian.gitee.io/2020/09/01/TCP%E9%9D%A2%E8%AF%95%E9%A2%98/">四次挥手</a>，断开连接。</li>
</ul>
<p><strong>HTTP1.0</strong></p>
<p>随着时代的进步，仅仅文本的传输无法满足需求，更多情况需要采用图文的方式才能生动的表达出自己的观点。随着1995年开发出Apache，同时其他的多媒体等技术发展迅速，从而进一步的促使HTTP新功能的出现。HTTP1.0在1996年诞生，增加了一下几个方面：</p>
<ul>
<li>之前只有Get方法，现在增加Post(加参数)，Head方法</li>
<li>加入协议版本号，同时添加文件处理类型</li>
<li>加入HTTP Header，让HTTP处理请求更加灵活</li>
<li>增加响应状态码，标记出错的原因</li>
<li>提供国际化(不同语言)支持</li>
</ul>
<p>典型的请求过程如下所示：</p>
<pre class="line-numbers language-html" data-language="html"><code class="language-html">GET /image.html HTTP/1.0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)

200 OK
Date: Tue, 17 Nov 2020 09:15:31 GMT
Content-Type: text/html
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>HTML</span><span class="token punctuation">></span></span> 
一个包含图片的页面
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>IMG</span> <span class="token attr-name">SRC</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/image.gif<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>HTML</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><strong>HTTP /1.1</strong></p>
<p>1995年是不平凡的一年，网景公司和微软开启浏览器大战，谁都想当老大。1999年HTTP/1.1发布并成为标准，写入RFC，以为以后不管是网关还是APP等，只要你要使用HTTP，就得遵守这个标准。</p>
<ul>
<li>继续增加了PUT等方法</li>
<li>允许持久连接</li>
</ul>
<p>随着文件越来越大，图片等信息越来越复杂，如果每一次上传下载文件都需要建立连接断开连接的过程将增加大量的开销。为此，提出了持久连接，也就是一次TCP连接可以具有多个HTTP请求。当然持久连接是可选择的，如果考虑关闭，只需要使用Connecttion:close关闭即可。</p>
<p><em>强制要求Host头</em></p>
<p>我们知道，在电商系统中，经常会因为促销活动导致流量飙升，为了缓解流量，其中有种方法即加缓存或者加服务器。如果是单台服务器负载过大，数据库可能分库分表。数据结构算法中分而治之方法亦是如此。那么HTTP中，同样的道理，如果文件太大，就大文件切分为小文件块发送。</p>
<p><strong>HTTP /2</strong></p>
<p>HTTP/1.1的出现，几年间出来大量很强的互联网公司，发展实在是太快，但是HTTP1.1中这几点成为诟病：</p>
<ul>
<li>原因1 TCP自带慢启动</li>
</ul>
<p>顾名思义，”慢启动”从0到1循循渐进。轿车启动不会按下按钮就直接起飞，而是缓慢调节到适合的速度。这不是挺好的？为什么会带来性能问题呢。我们知道一个页面有静态数据，动态页面，很多小文件在加载的过程中就会直接发起请求，这样导致太多的请求都会经历慢启动过程，花费时间太多。</p>
<ul>
<li>原因2 多条TCP连接带宽竞争</li>
</ul>
<p>带宽固定，多条TCP连接同时发起竞争带宽资源，由于各个TCP连接之间没有通信机制，也无法得知哪些资源优先级更高，从而导致想快速下载的资源反而延迟下载。</p>
<ul>
<li>原因3 头部阻塞</li>
</ul>
<p>阻塞，在网络编程中，我们采用异步，多路复用(epoll)方式尽量让cpu少等待多干事。在HTTP1.1中，虽然大家共用了一条TCP通道，但是第一个请求没有结束，第二请求就可能阻塞等待，也就是说不能同时发送接收数据。那么一个网页很多数据文件，如果能够同时发出请求，让部分数据文件能够得到响应并预处理，这样就大大的利用了带宽和cpu的资源。基于这些因素，在HTTP2中出现了新的方案。</p>
<p><em>如何解决头部阻塞呢？</em></p>
<p>HTTP是一问一答的模式，大家都在这个队列排队导致堵塞，那就多个队列并发进行，也就是”对同一个域名发起多个长连接”。举个例子，在火车站排队买票的时候，如果只有一个窗口可用，大家只能苦等，多开几个窗口就可缓解这个问题。</p>
<p>这个时候用户数 * 并发数(上限6-8)已经不错得效果，但是互联网速度太快，火车站就这么大，窗口也就这么多，怎么办，建新的火车站进行分流(大部分城市都有什么东站，西站)。在这里叫做”域名分片”，使用多个域名，这些域名指向同一服务器。</p>
<p><strong>HTTP/3</strong></p>
<p>HTTP/2看似很完美了吧，但是Google轮子哥可不服，其他人在研究HTTP/2的时候，它们就在琢磨QUIC。那QUIC有啥厉害的地方呢？</p>
<p>QUIC是Google开发的一个基于UDP且能像TCP一样具有可靠性特点的协议。具备像HTTP/2一样的应用数据二进制分帧传输。其主要解决的问题有两个。</p>
<ol>
<li>进一步解决线头阻塞问题。通过独立不同流，让各个流之间实现相互独立传输，互不干扰。</li>
<li>切换网络时的连接保持。wifi和3G/4G经常需要来回切换。基于TCP的协议，会因为网络的切换导致IP地址的改变。而基于UDP的QUIC协议，及时切换也可以恢复之前与服务器的连接。</li>
</ol>
<h2 id="HTTP报文详解"><a href="#HTTP报文详解" class="headerlink" title="HTTP报文详解"></a>HTTP报文详解</h2><p>客户端与服务端进行交互的信息为报文。客户端为请求报文，服务端为响应报文。我们先用wireshark抓一个博客看看。</p>
<pre class="line-numbers language-html" data-language="html"><code class="language-html">GET /article/12 HTTP/1.1
Host: www.xxx.cn
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION=so9nlsvenminor5abs65sh9dsa<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<pre class="line-numbers language-html" data-language="html"><code class="language-html">HTTP/1.1 200 OK
Server: nginx
Date: Sun, 17 May 2020 17:04:29 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: blade-2.0.6-BETA
Content-Encoding: gzip<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><strong>请求报文</strong></p>
<p><img src="https://api2.mubu.com/v3/document_image/4d931f16-f278-43d6-8f80-3365eb2b18dd-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/4d931f16-f278-43d6-8f80-3365eb2b18dd-3807603.jpg" class="lozad post-image"></p>
<p>请求报文通常由三部分组成：</p>
<ul>
<li>起始行：描述请求或者响应的基本信息</li>
<li>头部字段集合：key-value形式说明报文</li>
<li>消息正文：实际传输诸如图片等信息。具体如下</li>
</ul>
<ol>
<li><p>请求方法：一共有八种方法选择，如下表所示。采用不同的方法获取不同的资源。</p>
<table>
<thead>
<tr>
<th align="left">方法</th>
<th align="left">描述</th>
</tr>
</thead>
<tbody><tr>
<td align="left">GET</td>
<td align="left">请求指定的页面信息，并返回实体主体。</td>
</tr>
<tr>
<td align="left">HEAD</td>
<td align="left">类似于 GET 请求，只不过返回的响应中没有具体的内容，用于获取报头</td>
</tr>
<tr>
<td align="left">POST</td>
<td align="left">向指定资源提交数据进行处理请求（例如提交表单或者上传文件）。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。</td>
</tr>
<tr>
<td align="left">PUT</td>
<td align="left">从客户端向服务器传送的数据取代指定的文档的内容。</td>
</tr>
<tr>
<td align="left">DELETE</td>
<td align="left">请求服务器删除指定的页面。</td>
</tr>
<tr>
<td align="left">CONNECT</td>
<td align="left">HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。</td>
</tr>
<tr>
<td align="left">OPTIONS</td>
<td align="left">允许客户端查看服务器的性能。</td>
</tr>
<tr>
<td align="left">TRACE</td>
<td align="left">回显服务器收到的请求，主要用于测试或诊断。</td>
</tr>
<tr>
<td align="left">PATCH</td>
<td align="left">是对 PUT 方法的补充，用来对已知资源进行局部更新 。</td>
</tr>
</tbody></table>
</li>
<li><p>URI</p>
</li>
</ol>
<p>统一资源标识符(Uniform Resource Identifier),严格来说不等于网址，它包含URL和URN，可是URL太出名了以致于URL=”网址”。无论开发，测试运维配置都离不开URI,所以好好掌握。</p>
<p>网络层的IP主要目的是解决路由和寻址。现在的IP地址按照”.”分割，总共2的32次方大约42亿。对于计算机来说比较方便，但是对于人类来说还是不容易记忆，此时出现DNS了，他把IP地址映射为我们平时常见的”redis.org”，按照”.”分割域名，从左到右级别越高，最右边为”顶级域名”。如下图所示</p>
<p><img src="https://api2.mubu.com/v3/document_image/9620c4c7-effb-4206-a5df-3ef418b946c8-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/9620c4c7-effb-4206-a5df-3ef418b946c8-3807603.jpg" class="lozad post-image"></p>
<p>好了，现在TCP提供可靠(数据不丢失)且字节流(数据完整性)，而且也有方便我们记忆的域名，但是互联网资源千万种，也不知道访问什么(图片，文字，视频一大堆)，这个时候URI(统一资源标识符)出现了，如图所示：</p>
<p><img src="https://api2.mubu.com/v3/document_image/948dd51a-57f9-474f-9ea4-96ec6fb82c4f-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/948dd51a-57f9-474f-9ea4-96ec6fb82c4f-3807603.jpg" class="lozad post-image"></p>
<p><strong>协议名</strong>：HTTP协议，另外还有ftp等协议。告知访问资源时使用什么协议。</p>
<p>紧接着是分隔符:”://“</p>
<p><strong>主机名</strong>：标记互联网主机，可以是IP也可以是域名，如果不写端口则使用默认端口，例如HTTP为80，HTTPS为443.</p>
<p><strong>登录认证信息</strong>：登录主机时的用户名密码(不建议，直接告诉了别人你的隐私信息)</p>
<p><strong>主机名</strong>：此处可以是域名也可以是IP，如果不写端口号则是默认端口。比如HTTP默认端口为80，HTTPS默认端口为443</p>
<p><strong>资源所在位置</strong>：资源在主机上的位置，使用“/”分隔多级目录，在这里是“/en/download.html”。注意，必须”/“开头</p>
<p><strong>参数</strong>：用”?”开始，表示额外的请求要求。通常使用”key=value”的方式存在，如果多个”key=value”则使用”&amp;”相连。</p>
<p>既然规则这么多，对于接收方而言需要完成的解析也需要遵守规则，全球用户很多使用HTTP，每个国家地区所使用语言不同，HTTP为了能对其进行统一处理，引入了URI编码，方法比较简单，将非ASCII或者特殊字符全部转换为十六进制字节值，同时在前面加入”%”。比如空格被转换为”%20”,”中国”就编码为”%E4%B8%AD%E5%9B%BD%0A”。</p>
<ol start="3">
<li>请求体</li>
</ol>
<p>响应报文</p>
<p><img src="https://api2.mubu.com/v3/document_image/b49113f3-61c6-4558-a136-64ca4da63377-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/b49113f3-61c6-4558-a136-64ca4da63377-3807603.jpg" class="lozad post-image"></p>
<p>状态行—-服务器响应的状态<br>&lt;1&gt; 版本号：使用的HTTP什么版本<br>&lt;2&gt; 状态码：不同数字代表不同的结果，就如我们在编码时，通过返回不同的值代表不同的语义。<br>状态码一共分为5类：<br><strong>1××</strong><br>处于中间状态，还需后续操作</p>
<p><strong>200 OK</strong><br>最常见的成功状态码，表示一切正常，客户端获得期许的处理结果。如果不是Head请求，那么在响应头中通常会有body数据。</p>
<p><strong>204 No Content</strong><br>这个的含义和”200”很相似，不同之处在于它的响应头中没有body数据。</p>
<p><strong>206 Partial Content</strong><br>是 HTTP 分块下载或断点续传的基础，在客户端发送“范围请求”、要求获取资源的部分数据时出现，它与 200 一样，也是服务器成功处理了请求，但 body 里的数据不是资源的全部，而是其中的一部分。状态码 206 通常还会伴随着头字段“Content-Range”，表示响应报文里 body 数据的具体范围，供客户端确认，例如“Content-Range: bytes 0-99/5000”，意思是此次获取的是总计 5000 个字节的前 100 个字节。</p>
<p><strong>301 Moved Permanently</strong><br>“永久重定向”，意思是本地请求的资源以及不存在，使用新的URI再次访问。</p>
<p><strong>302 Found</strong><br>“Moved Temporarily”，“临时重定向”，临时则所请求的资源暂时还在，但是目前需要用另一个URI访问。</p>
<p>301 和 302 通过在字段Location中表明需要跳转的URI。两者最大的不同在于一个是临时改变，一个是永久改变。举个例子，有时候需要将网站全部升级为HTTPS，这种永久性改变就需要配置永久的”301”。有时候晚上更新系统，系统暂时不可用，可以配置”302”临时访问，此时不会做缓存优化，第二天还会访问原来的地址。</p>
<p><strong>304 Not Modified</strong><br>运用于缓存控制。它用于 If-Modified-Since 等条件请求，表示资源未修改，可以理解成“重定向已到缓存的文件”（即“缓存重定向”）。</p>
<p><strong>400 Bad Request</strong><br>通用错误码，表示请求报文有错误，但是这个错误过于笼统。不知道是客户端还是哪里的错误，所以在实际应用中，通常会返回含有明确含义的状态码。</p>
<p><strong>403 Forbidden</strong><br>注意了，这一个是表示服务器禁止访问资源。原因比如涉及到敏感词汇、法律禁止等。当然，如果能让客户端有一个清晰的认识，可以考虑说明拒绝的原因并返回即可。</p>
<p><strong>404 Not Found</strong><br>这可能是我们都知道且都不想看到的状态码之一，它的本意是想要的资源在本地未找到从而无法提供给服务端，但是现在，只要服务器”耍脾气”就会给你返回 404，而我们也无从得知后面到底是真的未找到，还是有什么别的原因。</p>
<p><strong>405 Method Not Allowed</strong><br>获取资源的方法好几种，我们可以对某些方法进行限制。例如不允许 POST 只能 GET。</p>
<p><strong>406 Not Acceptable</strong><br>客户端资源无法满足客户端请求的条件，例如请求需要中文但只有英文。</p>
<p><strong>408 Request Timeout</strong><br>请求超时，服务器等待了过长的时间。</p>
<p><strong>409 Conflict</strong><br>多个请求发生了冲突，可以理解为多线程并发时的竞态。</p>
<p><strong>413 Request Entity Too Large</strong><br>请求报文里的 body 太大。</p>
<p><strong>414 Request-URI Too Long</strong><br>请求行里的 URI 太大。</p>
<p><strong>429 Too Many Requests</strong><br>客户端发送了太多的请求，通常是由于服务器的限连策略。</p>
<p><strong>431 Request Header Fields Too Large</strong><br>请求头某个字段或总体太大。</p>
<p><strong>500 Internal Server Error</strong><br>和400 类似，属于一个通用的错误码，但是服务器到底是什么错误我们不得而知。其实这是好事，尽量少的将服务器资源暴露外网，尽量保证服务器的安全。</p>
<p><strong>502 Bad Gateway</strong><br>通常是服务器作为网关或者代理时返回的错误码，表示服务器自身工作正常，访问后端服务器时发生了错误，但具体的错误原因也是不知道的。</p>
<p><strong>503 Service Unavailable</strong><br>表示服务器当前很忙，暂时无法响应服务，我们上网时有时候遇到的“网络服务正忙，请稍后重试”的提示信息就是状态码 503。503 是一个“临时”的状态，暂时比较忙，稍后提供服务。在响应报文中的“Retry-After”字段，指示客户端可以在多久以后再次尝试发送请求。</p>
<ol start="4">
<li>请求体</li>
</ol>
<p>上面大部分都是涉及到header部分，还有非常重要的body，everybody</p>
<p>头字段注意事项：</p>
<p>&lt;1&gt; 字段名不区分大小写，例如“Host”也可以写成“host”，但首字母大写的可读性更好；<br>&lt;2&gt; 字段名里不允许出现空格，可以使用连字符“-”，但不能使用下划线”_”。例如，“test-name”是合法的字段名，而“test name”“test_name”是不正确的字段名；<br>&lt;3&gt; 字段名后面必须紧接着“:”，不能有空格，而”:”后的字段值前可以有多个空格；<br>&lt;4&gt; 字段的顺序是没有意义的，可以任意排列不影响语义；<br>&lt;5&gt; 字段原则上不能重复，除非这个字段本身的语义允许，例如 Set-Cookie。</p>
<p>HTTP的body常常被分为这几种的类别</p>
<p>&lt;1&gt; text:超文本text/html,纯文本text/plain<br>&lt;2&gt; audio/video:音视频数据<br>&lt;3&gt; application: 可能是文本，也可能是二进制，交给上层应用处理<br>&lt;4&gt; image: 图像文件。image/png等</p>
<p>但是带宽一定，数据大了通常考虑使用压缩算法进行压缩，在HTTP中使用Encoding type表示，常用的压缩方式有下面几种</p>
<p>&lt;1&gt; <strong>gzip</strong>:一种数据格式，默认且目前仅使用deflate算法压缩data部分<br>&lt;2&gt; <strong>deflate</strong>:一种压缩算法，是huffman编码的一种加强<br>&lt;3&gt; <strong>br</strong>:通过变种的LZ77算法、Huffman编码以及二阶文本建模等方式进行数据压缩，其他压缩算法相比，它有着更高的压塑压缩效率</p>
<p>使用相应的压缩方法在带宽一定的情况下确实有不错的效果，但是gzip等主要针对文件压缩效果不错，但是对视频就不行了。这个时候就可以使用数据结构中常用的分而治之，大化小再合并的方式：</p>
<p><img src="https://api2.mubu.com/v3/document_image/0a5a4ef2-adb6-467d-bb17-5f0dd19fcfbd-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/0a5a4ef2-adb6-467d-bb17-5f0dd19fcfbd-3807603.jpg" class="lozad post-image"></p>
<p>在报文中使用”Transer-Encoding:chunked”表示，代表body部分数据是分块传输的。另外在body中存在一个content-length字段表示body的长度，两者不能共存，另外很多时候是流式数据，body中没有指明content-length，这个时候一般就是chunked传输了。</p>
<p>现在可以通过采用分块的方式增强带宽的利用率，他的编码规则如图：</p>
<p>&lt;1&gt; 每一个分块包含长度和数据块<br>&lt;2&gt; 长度头按照CRLF结束<br>&lt;3&gt; 数据块在长度快后，且最后CRLF结尾<br>&lt;4&gt; 使用长度0表示结束，”0\r\n\r\n”</p>
<p>举个栗子</p>
<p><img src="https://api2.mubu.com/v3/document_image/a909c93f-3750-4c45-b56f-53f9904d5dca-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/a909c93f-3750-4c45-b56f-53f9904d5dca-3807603.jpg" class="lozad post-image"></p>
<p>分块解决了咋们一部分问题，但是有的时候我们想截断发送怎么办呢。在HTTP中提供了使用字段“Accept - Ranges: bytes”，明确告知客户端：“我是支持范围请求的”。那么Range范围是怎样的呢，Range从0开始计算，比如Range:0-5则读取前6个字节，服务器收到了这个请求，回应的方法为：</p>
<p>&lt;1&gt; 合法性检查。比如一共只有20字节，但是请求range：100-200。此时会返回416—-“范围请求有误”<br>&lt;2&gt; 范围正常，则返回216，表示请求数据知识一部分<br>&lt;3&gt; 服务器端在相应投资端增加Content-Range,格式”bytes x-y/length”。</p>
<p>断点续传怎么操作？</p>
<p>&lt;1&gt; 查看服务器是否支持范围请求并记录文件大小<br>&lt;2&gt; 多个线程分别负责不同的range<br>&lt;3&gt; 下载同时记录进度，即使因为网络等原因中断也没事，Range请求剩余即可</p>
<p>现在我们通过MIME-TYPE和Encoding-type可以知道body部分的类型，下一步将是对内容进行协商。HTTP中，请求体中使用Accept告诉服务端需要什么类型数据(我能处理哪些类型数据)，响应头中使用Content表明发送了什么类型数据，具体如下图所示</p>
<p><img src="https://api2.mubu.com/v3/document_image/598b5ea1-f264-4456-8aa5-f5eb018bf7c6-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/598b5ea1-f264-4456-8aa5-f5eb018bf7c6-3807603.jpg" class="lozad post-image"></p>
<p>好了，为了各个国家民族顺利友好的沟通和明确的区分。HTTP请求头中使用”type-subtype”，注意此时分隔符是”-“。比如en-GB表示英式英语，zh-CN表示常用的汉语，那对于客户端而言，它通过Accept-Language来标记自己可以理解的自然语言，对应的服务端使用Content-Language表明实体数据使用的语言类型，如下图所示。</p>
<p><img src="https://api2.mubu.com/v3/document_image/e3412578-8928-4d44-a613-1d5d7a3e1597-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/e3412578-8928-4d44-a613-1d5d7a3e1597-3807603.jpg" class="lozad post-image"></p>
<ol start="5">
<li>Cookie机制</li>
</ol>
<p>HTTP是无状态、无记忆的，Cookie机制的出现让其有记忆功能，如图：</p>
<p><img src="https://api2.mubu.com/v3/document_image/297daaec-341f-45bb-aa7e-87012cf5c260-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/297daaec-341f-45bb-aa7e-87012cf5c260-3807603.jpg" class="lozad post-image"></p>
<p>从上图我们可以知道Cookie是由浏览器负责存储，并不是操作系统负责，我们换个浏览器打开同样的网页，服务就认不出来了。</p>
<p>Cookie常见的应用一个是身份识别，一个是广告追踪，比如我们在访问网页视频或者图片的时候，广告商会悄悄给我们Cookie打上标记，方便做关联分析和行为分析，从而给我推荐一些相关内容。</p>
<ol start="6">
<li>HTTP代理</li>
</ol>
<p>之前介绍的都是一问一答的情景，但是在大部分的情况下都会存在多台服务器进行通信服务。其中比较常见的就是在请求方与应答方中间增加一个中间代理。</p>
<p><img src="https://api2.mubu.com/v3/document_image/e6822658-6c49-47dc-a058-27eaa2ef3292-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/e6822658-6c49-47dc-a058-27eaa2ef3292-3807603.jpg" class="lozad post-image"></p>
<p>代理作为中间位置，相对请求方为服务端，相当于后端服务端为请求方。代理常见的功能为负载均衡。在负载均衡中需要区分正向代理与反向代理，其中也就会涉及调度算法，比如轮询，一致性哈希等。</p>
<p><img src="https://api2.mubu.com/v3/document_image/636f4349-320a-4b1b-8135-32e112df6a92-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/636f4349-320a-4b1b-8135-32e112df6a92-3807603.jpg" class="lozad post-image"></p>
<h2 id="HTTPS"><a href="#HTTPS" class="headerlink" title="HTTPS"></a>HTTPS</h2><p>好人占多数，坏人也不少。总有些要搞坏事，因为HTTP是明文，所以需要想办法保护明文，从而出现了https。</p>
<p>安全四要素：</p>
<ul>
<li><strong>机密性</strong>：对信息进行保密，只能可信的人可以访问。</li>
<li><strong>完整性</strong>：数据在传输过程中内容不被”篡改”。虽然机密性对数据进行保密了，但是有上策也有下策(hack)。</li>
<li><strong>身份认证</strong>：证明自己的身份是本人，保证其消息发给可信的人。</li>
<li><strong>不可否认</strong>：君子一言驷马难追，说话算数，说过的话做过的事要有所保证。</li>
</ul>
<p><strong>HTTP和HTTPS结构上的区别</strong></p>
<p><img src="https://api2.mubu.com/v3/document_image/8236c213-60d3-44a6-b820-7a8b16f0d018-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/8236c213-60d3-44a6-b820-7a8b16f0d018-3807603.jpg" class="lozad post-image"></p>
<p>从上图我们知道HTTPS无非是在传输层和应用层中间加了一层TLS，正是TLS紧跟当代密码学的步伐，尽全力的保障用户的安全。我们用wireshark看看长什么样子。</p>
<p><img src="https://api2.mubu.com/v3/document_image/a3ae4c1f-c067-412c-97e5-fb286f15e7a3-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/a3ae4c1f-c067-412c-97e5-fb286f15e7a3-3807603.jpg" class="lozad post-image"></p>
<p>可以看出在交互的过程中多了不少新东西，了解TLS,TLS由SSL握手协议，SSL修改密码规范协议，SSL警报协议，SSL记录协议组成。</p>
<p><img src="https://api2.mubu.com/v3/document_image/7153d874-f7cd-47d7-8dd8-88065b7a3dc8-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/7153d874-f7cd-47d7-8dd8-88065b7a3dc8-3807603.jpg" class="lozad post-image"></p>
<p>SSL握手协议：</p>
<ul>
<li><strong>记录协议</strong>：记录为TLS发送接收数据的基本单位。它的自协议需要通过记录协议发出。如果多个纪录数据则可以一个TCP包一次性发出。</li>
<li><strong>警报协议</strong>：类似HTTP状态码，通过反馈不同的消息进行不同的策略。</li>
<li><strong>变更密码规范协议</strong>：告诉对方，从此刻开始，后续的数据将使用加密算法进行加密再传输。</li>
</ul>
<h3 id="对称加密"><a href="#对称加密" class="headerlink" title="对称加密"></a>对称加密</h3><p>对称加密，顾名思义，加密方与解密方使用同一钥匙(秘钥)。具体一些就是，发送方通过使用相应的加密算法和秘钥，对将要发送的信息进行加密；对于接收方而言，使用解密算法和相同的秘钥解锁信息，从而有能力阅读信息。</p>
<p><img src="https://api2.mubu.com/v3/document_image/309bb3e9-8df9-44e3-a9cd-9507658a16d7-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/309bb3e9-8df9-44e3-a9cd-9507658a16d7-3807603.jpg" class="lozad post-image"></p>
<h3 id="非对称加密"><a href="#非对称加密" class="headerlink" title="非对称加密"></a>非对称加密</h3><p>在对称加密中，发送方与接收方使用相同的秘钥。那么在非对称加密中则是发送方与接收方使用的不同的秘钥。其主要解决的问题是防止在秘钥协商的过程中发生泄漏。比如在对称加密中，小蓝将需要发送的消息加密，然后告诉你密码是123balala,ok,对于其他人而言，很容易就能劫持到密码是123balala。那么在非对称的情况下，小蓝告诉所有人密码是123balala,对于中间人而言，拿到也没用，因为没有私钥。所以，非对称密钥其实主要解决了密钥分发的难题。如下图</p>
<p><img src="https://api2.mubu.com/v3/document_image/d11f2adc-d53f-41e2-94b6-a3e809afa5b8-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/d11f2adc-d53f-41e2-94b6-a3e809afa5b8-3807603.jpg" class="lozad post-image"></p>
<p>其实我们经常都在使用非对称加密，比如使用多台服务器搭建大数据平台hadoop，为了方便多台机器设置免密登录，是不是就会涉及到秘钥分发。再比如搭建docker集群也会使用相关非对称加密算法。</p>
<h3 id="混合加密"><a href="#混合加密" class="headerlink" title="混合加密"></a>混合加密</h3><p>非对称加密算法，大多数是从数学问题演变而来，运算速度较慢。混合加密所谓取长补短。通信过程中使用RSA等解决密钥交换问题，然后使用随机数产生的在对称算法中的会话密钥，最后使用加密。对方使用私钥解密得到的密文取出会话秘钥，这样就实现了密钥交换。</p>
<p><img src="https://api2.mubu.com/v3/document_image/569008a7-ba90-4e08-bcd7-c5293bd4e324-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/569008a7-ba90-4e08-bcd7-c5293bd4e324-3807603.jpg" class="lozad post-image"></p>
<p>通过混淆加密等方式完成了机密性任务，作为Hack只需要伪造发布公钥或者作为之间人窃听密文。但是我们知道安全是四要素，还需要保证数据的完整性，身份认证等。</p>
<h3 id="摘要"><a href="#摘要" class="headerlink" title="摘要"></a>摘要</h3><p>摘要算法可以理解为一种特殊的”单向”加密算法，无密钥，不可逆。在平时项目中，应该大家都是用过MD5，SHA-1。但是在TLS中使用SHA-2。</p>
<p>假设小A转账5000给小C，小A加上SHA-2摘要。网站计算摘要并对比，如果一致则完整可信。</p>
<p><img src="https://api2.mubu.com/v3/document_image/53c8fd9e-5a86-4e6d-a89b-375285551fec-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/53c8fd9e-5a86-4e6d-a89b-375285551fec-3807603.jpg" class="lozad post-image"></p>
<p>此时小B想修改小A给的money，这个时候网站计算摘要就会发现不一样，不可信。</p>
<p><img src="https://api2.mubu.com/v3/document_image/53c8fd9e-5a86-4e6d-a89b-375285551fec-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/53c8fd9e-5a86-4e6d-a89b-375285551fec-3807603.jpg" class="lozad post-image"></p>
<p>HTTPS请求建立连接过程</p>
<p><img src="https://api2.mubu.com/v3/document_image/358cc91e-eb98-4e07-88e2-7e198c1d15da-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/358cc91e-eb98-4e07-88e2-7e198c1d15da-3807603.jpg" class="lozad post-image"></p>
<p><strong>注意：</strong></p>
<ol>
<li>首先通过非对称加密建立通信过程</li>
<li>在握手阶段，为什么使用3个随机数，一方面防止「随机数 C」被猜出，另一方增加Session key随机性</li>
<li>Client发出支持的「对称/非对称加密」算法</li>
<li>server返回选用的「对称/非对称加密」算法</li>
<li>Client对算法进行确认</li>
<li>Server对算法进行确认</li>
</ol>
<p>根据wireshak结果，对TLS进一步剖析。TCP三次握手建立连接，作为礼貌，Client先打招呼”Client Hello”。里面包含了Client的版本号、所支持的密码套件和随机数，如下图所示</p>
<p><img src="https://api2.mubu.com/v3/document_image/bdc8dda7-80f0-412d-893a-f1a49005921c-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/bdc8dda7-80f0-412d-893a-f1a49005921c-3807603.jpg" class="lozad post-image"></p>
<p>Server端表示尊重，回复”Server Hello”,同时进行版本校对，给出随机数(Server Random)，从Client算法列表中选择一个密码套件，在这里选择的”TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”。</p>
<p><img src="https://api2.mubu.com/v3/document_image/ce00a904-7228-4fef-8739-3e09c5a9e5b6-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/ce00a904-7228-4fef-8739-3e09c5a9e5b6-3807603.jpg" class="lozad post-image"></p>
<p>这里的”TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”的意思是密码套件选择椭圆曲线加RSA、AES、SHA256</p>
<p>双方通过证书验证身份。因为本机服务器选用了ECDHE算法，为了实现密钥交换算法，它会发送证书后把椭圆曲线的公钥（Server Params）连带”Server Key Exchange”消息发送出去。</p>
<p><img src="https://api2.mubu.com/v3/document_image/ecc60ac4-3d14-4481-ba6c-d763ddabe500-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/ecc60ac4-3d14-4481-ba6c-d763ddabe500-3807603.jpg" class="lozad post-image"></p>
<p>意思是，刚才混合加密套件比较复杂，给你个算法参数，好好记住，别弄丢了。</p>
<p><img src="https://api2.mubu.com/v3/document_image/eab584f8-017a-4b31-a310-8eec14be03e0-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/eab584f8-017a-4b31-a310-8eec14be03e0-3807603.jpg" class="lozad post-image"></p>
<p>随后服务端回复”hello done”告知打招呼完毕</p>
<p>打完招呼完毕后，客户端对证书进行核实。然后根据密码套件也生成椭圆曲线的公钥，用”Client Key Exchange”消息发给服务器</p>
<p><img src="https://api2.mubu.com/v3/document_image/e9204c93-dc8b-4a61-a17e-10242954c1bd-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/e9204c93-dc8b-4a61-a17e-10242954c1bd-3807603.jpg" class="lozad post-image"></p>
<p>此时客户端和服务端都有了密钥交换的两个参数(Client Params、ServerParams），然后通过 ECDHE 算法算出了一个新的值，叫“Pre-Master”</p>
<p>有了主密钥和会话密钥，客户端发送“Change Cipher Spec”和“Finished”消息，最后将所有消息加上摘要发送给服务器验证。</p>
<p>服务器同样发送“Change Cipher Spec”和“Finished”消息，握手结束，开始进行HTTP请求与响应。</p>
<h2 id="HTTP特点小结"><a href="#HTTP特点小结" class="headerlink" title="HTTP特点小结"></a>HTTP特点小结</h2><p>写到这里，说它简单是假的，简单的东西通常更具有扩展的可能性。根据需求的变更，越来越复杂。</p>
<ol>
<li><strong>灵活且易扩展</strong>，他的头部字段很多都是可定制且可扩展</li>
<li><strong>应用广泛</strong>。各个领域都有涉及。”跨平台，跨语言”</li>
<li><strong>无状态</strong>。没有记忆功能，少功能即少占用资源。另外无状态更容易搭建集群，通过负载均衡将请求转发到任意一台服务器。缺点是无法支持需要连续步骤的”事务”操作。我们知道TCP协议有11种状态，不同状态代表通信过程中不同的含义。同样操作系统中的进程也有执行，就绪，活动阻塞等多种状态。但是HTTP全程都是”懵逼”无状态。比如小华请求服务器获取视频X，服务器觉得可行就发给小华。小华还想获取视频Y，这时服务器不会记录之前的状态，也就不知道这两个请求是否是同一个，所以小华还得告诉服务器自己的身份。</li>
<li>** 明文**。优点是能让开发人员通过wireshark工具更直观的调试。缺点即裸奔互联网，没隐私可言。</li>
<li><strong>可靠传输</strong>。HTTP为应用层协议，基于TCP/IP，而TCP为“可靠”传输协议，因此HTTP能在请求应答中”可靠”传输数据。</li>
<li><strong>应用层协议</strong>。应用层协议很多，其中常用的邮件协议SMTP，上传下载文件ftp，默认端口22/23，SSH远程登录(XSHELL)。这些应用层协议都太专一，而HTTP通过各种头部字段，实体数据的组合，并综合缓存代理等功能，不得不说是网络中的冠希哥。</li>
</ol>
<h2 id="HTTP识别-还原"><a href="#HTTP识别-还原" class="headerlink" title="HTTP识别(还原)"></a>HTTP识别(还原)</h2><p>这里说的识别，通过代码层面(libpcap封装)实现HTTP的识别，也能进一步体现TCP/IP协议栈的分层特性。先看回忆一下IP头部格式。</p>
<p><img src="https://api2.mubu.com/v3/document_image/0445b790-b02a-4a41-ad01-7638cbd5df14-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/0445b790-b02a-4a41-ad01-7638cbd5df14-3807603.jpg" class="lozad post-image"></p>
<p>注意头部中的协议字段，如果此字段值为0x0600则为TCP分组。当知道了是TCP分组后，是不是可以通过TCP头部中端口(80)就可以判断为HTTP呢，不能的，很多情况都会使用动态端口的方式进行部署。此时可以通过HTTP中的关键字进行判断。如果为HTTP，再通过头部字段中的”Content-type”，charset等确认文本信息，编码方式，最后采用解码算法进行还原。</p>
<h2 id="HTTPS-密文-识别"><a href="#HTTPS-密文-识别" class="headerlink" title="HTTPS(密文)识别"></a>HTTPS(密文)识别</h2><p>方法一也是比较直接的方法是直接通过抓包工具，插件配置即可。这里想给大家分享另一种思路和在Linux持续捕包的方法。</p>
<ul>
<li>数据集采集<br>使用python的dpkt库(pip install dpkt即可)，dpkt库方便对每一层协议进行拆解，同时也能进行流的拆分以及特征的提取。下面举一个通过无头浏览的方式自动化采集流量(ps如果需要较大规模的流量采集则可以考虑使用docker集群的方式)</li>
</ul>
<p><img src="https://api2.mubu.com/v3/document_image/c5f31555-714f-43dc-87ec-37bed6699deb-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/c5f31555-714f-43dc-87ec-37bed6699deb-3807603.jpg" class="lozad post-image"></p>
<ul>
<li>根据所提特征生成npz(实际上是numpy提供的数组存储方式)</li>
<li>使用开源skearn库进行模型训练并识别预测，此处假设使用SVM(仅使用默认参数)</li>
</ul>
<p><img src="https://api2.mubu.com/v3/document_image/12d9ade3-403e-4e23-b787-90601920947d-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/12d9ade3-403e-4e23-b787-90601920947d-3807603.jpg" class="lozad post-image"></p>
<ul>
<li>识别结果(参数进行适度调整定会更好的效果)</li>
</ul>
<p><img src="https://api2.mubu.com/v3/document_image/646611f8-ef93-4c7c-96fa-455c80ef20ec-3807603.jpg" alt="t0" srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="https://api2.mubu.com/v3/document_image/646611f8-ef93-4c7c-96fa-455c80ef20ec-3807603.jpg" class="lozad post-image"></p>
<h2 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h2><p><a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/8HJ-V1BbV9wp89HS-XulXw">一文彻底拿下HTTP/HTTPS协议</a></p>

  </div>
  <div>
    
  </div>
</article>
<div class="nav">
  
    <div class="nav-item-prev">
      <a 
        href="/2021/06/13/HTTPSWorksWithTheTCPHandshakeMechanism/" 
        class="nav-link">
        <i class="iconfont icon-left nav-prev-icon"></i>
        <div>
          <div class="nav-label">上一篇</div>
          
            <div class="nav-title">HTTPS的工作原理 </div>
          
        </div>
      </a>
    </div>
  
  
    <div class="nav-item-next">
      <a 
        href="/2021/06/13/HTTP,HTTP2.0,SPDY,HTTPSSomethingYouShouldKnow/" 
        class="nav-link">
        <div>
          <div class="nav-label">下一篇</div>
          
            <div class="nav-title">HTTP,HTTP2.0,SPDY,HTTPS 你应该知道的一些事 </div>
          
        </div>
        <i class="iconfont icon-right nav-next-icon"></i>
      </a>
    </div>
  
</div>

<div 
  class="card card-content toc-card" 
  id="mobiletoc">
  <div class="toc-header">
  <i 
    class="iconfont icon-menu" 
    style="padding-right: 2px;">
  </i>目录
</div>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E8%A8%80"><span class="toc-text">前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E6%98%AF%E4%BB%80%E4%B9%88"><span class="toc-text">HTTP是什么</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%E7%9A%84HTTP"><span class="toc-text">不同版本的HTTP</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E6%8A%A5%E6%96%87%E8%AF%A6%E8%A7%A3"><span class="toc-text">HTTP报文详解</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTPS"><span class="toc-text">HTTPS</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86"><span class="toc-text">对称加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86"><span class="toc-text">非对称加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B7%B7%E5%90%88%E5%8A%A0%E5%AF%86"><span class="toc-text">混合加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%91%98%E8%A6%81"><span class="toc-text">摘要</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E7%89%B9%E7%82%B9%E5%B0%8F%E7%BB%93"><span class="toc-text">HTTP特点小结</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E8%AF%86%E5%88%AB-%E8%BF%98%E5%8E%9F"><span class="toc-text">HTTP识别(还原)</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTPS-%E5%AF%86%E6%96%87-%E8%AF%86%E5%88%AB"><span class="toc-text">HTTPS(密文)识别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5"><span class="toc-text">参考链接</span></a></li></ol>
</div></main>
            <aside class="left-column">
              
              <div class="card card-author">
                
  <img 
    src="https://api2.mubu.com/v3/photo/654b368e-b847-4122-982c-86d90b3f5275.jpg" 
    class="author-img" 
    alt="author avatar">

<p class="author-name">霜序廿</p>
<p class="author-description">无限进步</p>
<div class="author-message">
  <a 
    class="author-posts-count" 
    href="/archives">
    <span>253</span>
    <span>文章</span>
  </a>
  <a 
    class="author-categories-count" 
    href="/categories">
    <span>6</span>
    <span>分类</span>
  </a>
  <a 
    class="author-tags-count" 
    href="/tags">
    <span>51</span>
    <span>标签</span>
  </a>
</div>

  <div class="author-card-society">
    
      <div class="author-card-society-icon">
        <a target="_blank" rel="noopener" href="https://github.com/shuangxunian">
          <i class="iconfont icon-github society-icon"></i>
        </a>
      </div>
    
      <div class="author-card-society-icon">
        <a target="_blank" rel="noopener" href="https://space.bilibili.com/391117803">
          <i class="iconfont icon-bilibili society-icon"></i>
        </a>
      </div>
    
  </div>

              </div>
               <div class="sticky-tablet">
  
  
    <article class="display-when-two-columns spacer">
      <div class="card card-content toc-card">
        <div class="toc-header">
  <i 
    class="iconfont icon-menu" 
    style="padding-right: 2px;">
  </i>目录
</div>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E8%A8%80"><span class="toc-text">前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E6%98%AF%E4%BB%80%E4%B9%88"><span class="toc-text">HTTP是什么</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%E7%9A%84HTTP"><span class="toc-text">不同版本的HTTP</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E6%8A%A5%E6%96%87%E8%AF%A6%E8%A7%A3"><span class="toc-text">HTTP报文详解</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTPS"><span class="toc-text">HTTPS</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86"><span class="toc-text">对称加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86"><span class="toc-text">非对称加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B7%B7%E5%90%88%E5%8A%A0%E5%AF%86"><span class="toc-text">混合加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%91%98%E8%A6%81"><span class="toc-text">摘要</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E7%89%B9%E7%82%B9%E5%B0%8F%E7%BB%93"><span class="toc-text">HTTP特点小结</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E8%AF%86%E5%88%AB-%E8%BF%98%E5%8E%9F"><span class="toc-text">HTTP识别(还原)</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTPS-%E5%AF%86%E6%96%87-%E8%AF%86%E5%88%AB"><span class="toc-text">HTTPS(密文)识别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5"><span class="toc-text">参考链接</span></a></li></ol>
      </div>
    </article>
  
  
  <article class="card card-content categories-widget">
    <div class="categories-card">
  <div class="categories-header">
    <i 
      class="iconfont icon-fenlei" 
      style="padding-right: 2px;">
    </i>分类
  </div>
  <div class="categories-list">
    
      <a href="/categories/%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0/">
        <div class="categories-list-item">
          技术文章
          <span class="categories-list-item-badge">218</span>
        </div>
      </a>
    
      <a href="/categories/%E5%85%B6%E4%BB%96/">
        <div class="categories-list-item">
          其他
          <span class="categories-list-item-badge">16</span>
        </div>
      </a>
    
      <a href="/categories/%E6%97%85%E6%B8%B8/">
        <div class="categories-list-item">
          旅游
          <span class="categories-list-item-badge">1</span>
        </div>
      </a>
    
      <a href="/categories/%E7%AE%97%E6%B3%95/">
        <div class="categories-list-item">
          算法
          <span class="categories-list-item-badge">8</span>
        </div>
      </a>
    
      <a href="/categories/%E8%80%83%E8%AF%95/">
        <div class="categories-list-item">
          考试
          <span class="categories-list-item-badge">8</span>
        </div>
      </a>
    
      <a href="/categories/%E9%98%85%E8%AF%BB/">
        <div class="categories-list-item">
          阅读
          <span class="categories-list-item-badge">1</span>
        </div>
      </a>
    
  </div>
</div>
  </article>
  
  <article class="card card-content tags-widget">
    <div class="tags-card">
  <div class="tags-header">
    <i 
      class="iconfont icon-biaoqian" 
      style="padding-right: 2px;">
    </i>热门标签
  </div>
  <div class="tags-list">
    
      <a 
        href="/tags/js/" 
        title="js">
        <div class="tags-list-item">js</div>
      </a>
    
      <a 
        href="/tags/vue/" 
        title="vue">
        <div class="tags-list-item">vue</div>
      </a>
    
      <a 
        href="/tags/%E9%9D%A2%E8%AF%95/" 
        title="面试">
        <div class="tags-list-item">面试</div>
      </a>
    
      <a 
        href="/tags/css/" 
        title="css">
        <div class="tags-list-item">css</div>
      </a>
    
      <a 
        href="/tags/%E7%BD%91%E7%BB%9C/" 
        title="网络">
        <div class="tags-list-item">网络</div>
      </a>
    
      <a 
        href="/tags/%E5%85%B6%E4%BB%96/" 
        title="其他">
        <div class="tags-list-item">其他</div>
      </a>
    
      <a 
        href="/tags/%E7%AE%97%E6%B3%95/" 
        title="算法">
        <div class="tags-list-item">算法</div>
      </a>
    
      <a 
        href="/tags/%E6%B5%8F%E8%A7%88%E5%99%A8/" 
        title="浏览器">
        <div class="tags-list-item">浏览器</div>
      </a>
    
      <a 
        href="/tags/html/" 
        title="html">
        <div class="tags-list-item">html</div>
      </a>
    
      <a 
        href="/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" 
        title="操作系统">
        <div class="tags-list-item">操作系统</div>
      </a>
    
      <a 
        href="/tags/%E8%80%83%E8%AF%95/" 
        title="考试">
        <div class="tags-list-item">考试</div>
      </a>
    
      <a 
        href="/tags/%E8%BD%AF%E5%AE%9E%E5%8A%9B/" 
        title="软实力">
        <div class="tags-list-item">软实力</div>
      </a>
    
      <a 
        href="/tags/DOM/" 
        title="DOM">
        <div class="tags-list-item">DOM</div>
      </a>
    
      <a 
        href="/tags/%E8%BD%AE%E5%AD%90/" 
        title="轮子">
        <div class="tags-list-item">轮子</div>
      </a>
    
      <a 
        href="/tags/%E7%BD%91%E7%BB%9C%E5%8E%9F%E7%90%86/" 
        title="网络原理">
        <div class="tags-list-item">网络原理</div>
      </a>
    
      <a 
        href="/tags/debug/" 
        title="debug">
        <div class="tags-list-item">debug</div>
      </a>
    
  </div>
</div>
  </article>
  
  
</div>
            </aside>
            <aside class="right-column">
              <div class="sticky-widescreen">
  
  
    <article class="card card-content toc-card">
      <div class="toc-header">
  <i 
    class="iconfont icon-menu" 
    style="padding-right: 2px;">
  </i>目录
</div>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E8%A8%80"><span class="toc-text">前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E6%98%AF%E4%BB%80%E4%B9%88"><span class="toc-text">HTTP是什么</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%E7%9A%84HTTP"><span class="toc-text">不同版本的HTTP</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E6%8A%A5%E6%96%87%E8%AF%A6%E8%A7%A3"><span class="toc-text">HTTP报文详解</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTPS"><span class="toc-text">HTTPS</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86"><span class="toc-text">对称加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86"><span class="toc-text">非对称加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B7%B7%E5%90%88%E5%8A%A0%E5%AF%86"><span class="toc-text">混合加密</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%91%98%E8%A6%81"><span class="toc-text">摘要</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E7%89%B9%E7%82%B9%E5%B0%8F%E7%BB%93"><span class="toc-text">HTTP特点小结</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTP%E8%AF%86%E5%88%AB-%E8%BF%98%E5%8E%9F"><span class="toc-text">HTTP识别(还原)</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HTTPS-%E5%AF%86%E6%96%87-%E8%AF%86%E5%88%AB"><span class="toc-text">HTTPS(密文)识别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5"><span class="toc-text">参考链接</span></a></li></ol>
    </article>
  
  
  <article class="card card-content">
    <div class="recent-posts-card">
  <div class="recent-posts-header">
    <i 
      class="iconfont icon-wenzhang_huaban" 
      style="padding-right: 2px;">
    </i>最近文章
  </div>
  <div class="recent-posts-list">
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2022-05-01</div>
        <a href="/2022/05/01/typescriptHome/"><div class="recent-posts-item-content">typescript</div></a>
      </div>
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2022-01-15</div>
        <a href="/2022/01/15/javaScriptTheVariousWaysAndAdvantagesAndDisadvantagesOfDeepInheritance/"><div class="recent-posts-item-content">JavaScript深入之继承的多种方式和优缺点</div></a>
      </div>
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2022-01-15</div>
        <a href="/2022/01/15/javaScriptGoFromPrototypeToPrototypeChain/"><div class="recent-posts-item-content">JavaScript深入之从原型到原型链</div></a>
      </div>
    
      <div class="recent-posts-item">
        <div class="recent-posts-item-title">2022-01-15</div>
        <a href="/2022/01/15/javaScriptMemoryLeakTutorial/"><div class="recent-posts-item-content">JavaScript 内存泄漏教程</div></a>
      </div>
    
  </div>
</div>
  </article>
  
  
  
  <article class="card card-content">
    <div class="recent-posts-card">
  <div class="recent-posts-header">
    关注嘉然！顿顿解馋！
  </div>
  <div class="recent-posts-list">
    
      <img 
        src="https://api2.mubu.com/v3/document_image/2697c6ae-10ee-41a3-9099-304bdb252d31-3807603.jpg" 
        class="myadd-img" 
        alt="author avatar">
    
  </div>
</div>
  </article>
</div>
            </aside>
          </div>
        </div>
      </div>
    </div>
     
    <footer class="footer">
  <div class="footer-container">
    <div>
      <div class="footer-dsc">
        <span>
          Copyright ©
          
            2020 -
          
          2022
        </span>
        &nbsp;
        <a 
          href="/" 
          class="footer-link">
          霜序廿的个人网站
        </a>
      </div>
    </div>

    
      <div class="footer-dsc">
        
          Powered by
          <a 
            href="https://hexo.io/" 
            class="footer-link" 
            target="_blank" 
            rel="nofollow noopener noreferrer">
            &nbsp;Hexo
          </a>
        
        
          <span>&nbsp;|&nbsp;</span>
        
        
          Theme -
          <a 
            href="https://github.com/theme-kaze" 
            class="footer-link" 
            target="_blank"
            rel="nofollow noopener noreferrer">
            &nbsp;Kaze
          </a>
        
      </div>
    
    
    
    
</footer> 
    
  <a 
    role="button" 
    id="scrollbutton" 
    class="basebutton" 
    aria-label="回到顶部">
    <i class="iconfont icon-arrowleft button-icon"></i>
  </a>

<a 
  role="button" 
  id="menubutton" 
  class="basebutton">
  <i class="iconfont icon-menu button-icon"></i>
</a>
<a 
  role="button" 
  id="popbutton" 
  class="basebutton" 
  aria-label="控制中心">
  <i class="iconfont icon-expand button-icon"></i>
</a>
<a 
  role="button" 
  id="darkbutton" 
  class="basebutton darkwidget" 
  aria-label="夜色模式">
  <i class="iconfont icon-weather button-icon"></i>
</a>
<a 
  role="button" 
  id="searchbutton" 
  class="basebutton searchwidget" 
  aria-label="搜索">
  <i class="iconfont icon-search button-icon"></i>
</a> 
     
     
     
      <script>
  var addImgLayout = function () {
    var img = document.querySelectorAll('.post-content img')
    var i
    for (i = 0; i < img.length; i++) {
      var wrapper = document.createElement('a')
      wrapper.setAttribute('href', img[i].getAttribute('data-src'))
      wrapper.setAttribute('aria-label', 'illustration')
      wrapper.style.cssText =
        'width: 100%; display: flex; justify-content: center;'
      if (img[i].alt) wrapper.dataset.caption = img[i].alt
      wrapper.dataset.nolink = true
      img[i].before(wrapper)
      wrapper.append(img[i])
      var divWrap = document.createElement('div')
      divWrap.classList.add('gallery')
      wrapper.before(divWrap)
      divWrap.append(wrapper)
    }
    baguetteBox.run('.gallery')
  }
</script>
<script>
  loadScript(
    "/js/lib/lightbox/baguetteBox.min.js",
    addImgLayout
  )
</script>
 
     
     
    <script src="/js/main.js"></script> 
     
    
      <script>
        var addLazyload = function () {
          var observer = lozad('.lozad', {
            load: function (el) {
              el.srcset = el.getAttribute('data-src')
            },
            loaded: function (el) {
              el.classList.add('loaded')
            },
          })
          observer.observe()
        }
      </script>
      <script>
        loadScript('/js/lib/lozad.min.js', addLazyload)
      </script>
     
    
    
  </body>
</html>
